var gBACKCOLOR ="#ccf533";
var gTEXTBACKCOLOR ="#e99bff";

function CompareById(v_nodeID1, v_nodeID2)
{
    var LeftContentObj = document.getElementById(v_nodeID1);
    var RightContentObj = document.getElementById(v_nodeID2);

    var LeftNodesList = new Array;
    LeftNodesList = GetAllTextNodes(LeftContentObj);

    var RightNodesList = new Array;
    RightNodesList = GetAllTextNodes(RightContentObj);

    CompareNodes(LeftNodesList, RightNodesList);
}
function Equal(v_node1, v_node2)
{
    if (v_node1.data == v_node2.data)
        return true;
    return false;
}
function CompareText(v_LeftList, v_RightList)
{
    var leftLen = v_LeftList.length;
    var rightLen = v_RightList.length;
    if (rightLen == leftLen && 1 == rightLen)
    {
        if (v_LeftList[0].data.length==v_RightList[0].data.length && 1==v_RightList[0].data.length )
            return;
    }
    if (0 == leftLen)
    {
        for (var i = 0; i < rightLen; i++)
            PaintNode(v_RightList[i], gTEXTBACKCOLOR);
    }
    else if (0 == rightLen)
    {
        for (var i = 0; i < leftLen; i++)
            PaintNode(v_LeftList[i], gTEXTBACKCOLOR);
    }
    else
    {
        //--------------------compare text--------------------
        var LeftTextList = new Array;
        LeftTextList = GetCharList(v_LeftList);
        var RightTextList = new Array;
        RightTextList = GetCharList(v_RightList);

        var ResultList = new Array;
        ResultList = CompareChars(LeftTextList, RightTextList);
        if (0 != ResultList[0].length || 0 != ResultList[1].length)
        {
            for (var i = 0; i < v_LeftList.length; i++)
                v_LeftList[i] = PaintNode(v_LeftList[i], gBACKCOLOR);

            for (var i = 0; i < v_RightList.length; i++)
                v_RightList[i] = PaintNode(v_RightList[i], gBACKCOLOR);
        }

        Display(ResultList[0], v_LeftList);
        Display(ResultList[1], v_RightList);
        //------------------------END-------------------------
    }
}

function GetCharList(v_nodeList)
{
    var CharList = new Array;
    for (var i = 0; i < v_nodeList.length; i++)
    {
        var text = v_nodeList[i].data;
        for (var j = 0; j < text.length; j++)
        {
            CharList[CharList.length] = text.charAt(j);
        }
    }
    return CharList;
}
function Display(v_posList, v_nodeList)
{
    var NodeTextList = new Array;
    if (0 == v_posList.length)
        return;

    for (var i = 0; i < v_nodeList.length; i++)
    {
        NodeTextList.length = 0;
        var splitPos = new Array;
        if (1 == v_nodeList.length)
            splitPos = v_posList;
        else
        {
            var begin = 0;
            if (i > 0)
            {
                for (var k = 0; k < i; k++)
                    begin += v_nodeList[k].data.length;
            }
            splitPos = GetSplitPosList(v_posList, v_nodeList[i].data.length, begin);
        }

        NodeTextList = SplitTexe(splitPos, v_nodeList[i].data);
        PaintText(v_nodeList[i], NodeTextList, gTEXTBACKCOLOR);
    }
}

function GetSplitPosList(v_list, v_len, v_begin)
{
    var splitPos = new Array;
    var preLen = 0;
    for (var j = 0; j < v_list.length/2; j++)
    {
        if (v_list[2*j] <= v_begin)
        {
            if (v_list[2*j + 1] < v_begin)
                continue;
            else if (v_list[2*j + 1] > v_begin + v_len - 1)
            {
                splitPos[splitPos.length] = v_list[2*j] - v_begin + preLen;
                splitPos[splitPos.length] = v_len - 1 + preLen;
                break;
            }
            else
            {
                splitPos[splitPos.length] = preLen;
                splitPos[splitPos.length] = v_list[2*j + 1] - v_begin + preLen;
                preLen = preLen + v_list[2*j + 1] - v_begin +1;
                v_len = v_len - v_list[2*j + 1] + v_begin -1;
                if (0 == v_len)
                    break;
                v_begin = v_list[2*j + 1] + 1;
            }
        }
        else
        {
            if (v_list[2*j] > v_begin + v_len - 1)
                break;
            else if (v_list[2*j + 1] >= v_begin + v_len - 1)
            {
                splitPos[splitPos.length] = v_list[2*j] - v_begin + preLen;
                splitPos[splitPos.length] = v_len - 1 + preLen;
                break;
            }
            else
            {
                splitPos[splitPos.length] = v_list[2*j] - v_begin + preLen;
                splitPos[splitPos.length] = v_list[2*j + 1] - v_begin + preLen;
                preLen = preLen + v_list[2*j + 1] - v_begin +1;
                v_len = v_len - v_list[2*j + 1] + v_begin -1;
                if (0 == v_len)
                    break;
                v_begin = v_list[2*j + 1] + 1;
            }
        }
    }

    return splitPos;
}
function SplitTexe(v_splitPosList, v_text)
{
    var NodeTextList = new Array;
    var begin = 0;
    for (var j = 0; j < v_splitPosList.length/2; j++)
    {
        if (v_splitPosList[2*j] > 0)
            NodeTextList[2*j] = v_text.substring(begin, v_splitPosList[2*j]);
        else
            NodeTextList[2*j] = null;
        NodeTextList[2*j + 1] = v_text.substring(v_splitPosList[2*j], v_splitPosList[2*j + 1] + 1);

        begin = v_splitPosList[2*j + 1] + 1;
    }
    if (begin < v_text.length)
    {
        NodeTextList[NodeTextList.length] = v_text.substring(begin, v_text.length + 1);
        NodeTextList[NodeTextList.length] = null;
    }
    return NodeTextList;
}

function PaintText(v_node, v_textList, v_color)
{
    var newNodeTextList = new Array;
    for (var i = 0; i < v_textList.length; i=i+2)
    {
        if (v_textList[i] == null)
            newNodeTextList[i] = null;
        else
            newNodeTextList[i] = document.createTextNode(v_textList[i]);

        if (v_textList[i+1] == null)
            newNodeTextList[i+1] = null;
        else
        {
            var temp = document.createTextNode(v_textList[i+1]);
            var new_Node = document.createElement('SPAN');
            new_Node.style.background = v_color;
            new_Node.appendChild(temp);
            newNodeTextList[i+1] = new_Node;
        }

    }

    var fatherNode = v_node.parentNode;
    fatherNode.removeChild(v_node);
    for (var i = 0; i < newNodeTextList.length; i++)
    {
        if (newNodeTextList[i] != null)
            fatherNode.appendChild(newNodeTextList[i]);
    }
}

function CompareChars(v_LeftCharsList, v_RightCharsList)
{
    var ResultList = new Array;
    var RightDiffList = new Array;
    var LeftDiffList = new Array;

    var RightIndex =0;
    var LeftIndex =0;
    var nLeftCharsListLen = v_LeftCharsList.length;
    var nRightCharsListLen = v_RightCharsList.length;
    if (nLeftCharsListLen == nRightCharsListLen)
    {
        for (var i = 0; i < nLeftCharsListLen; i++)
        {
            if (v_LeftCharsList[i] == v_RightCharsList[i])
            {
                if (i - LeftIndex != 0)
                {
                    LeftDiffList[LeftDiffList.length] = LeftIndex;
                    LeftDiffList[LeftDiffList.length] = i - 1;

                    RightDiffList[RightDiffList.length] = RightIndex;
                    RightDiffList[RightDiffList.length] = i - 1;
                }
                LeftIndex = i + 1;
                RightIndex = i + 1;
            }
        }
        if (LeftIndex != nLeftCharsListLen )
        {
            LeftDiffList[LeftDiffList.length] = LeftIndex;
            LeftDiffList[LeftDiffList.length] = nLeftCharsListLen - 1;

            RightDiffList[RightDiffList.length] = RightIndex;
            RightDiffList[RightDiffList.length] = nLeftCharsListLen - 1;
        }
        ResultList[0] = LeftDiffList;
        ResultList[1] = RightDiffList;
        return ResultList;
    }

    while(LeftIndex < nLeftCharsListLen || RightIndex < nRightCharsListLen)
    {
        ///left is end
        if (LeftIndex == nLeftCharsListLen)
        {
            RightDiffList[RightDiffList.length] = RightIndex;
            RightDiffList[RightDiffList.length] = nRightCharsListLen - 1;
            break;
        }
        ///right is end
        if (RightIndex == nRightCharsListLen)
        {
            LeftDiffList[LeftDiffList.length] = LeftIndex;
            LeftDiffList[LeftDiffList.length] = nLeftCharsListLen - 1;
            break;
        }

        if (v_LeftCharsList[LeftIndex] == v_RightCharsList[RightIndex])
        {
            ///same
            LeftIndex++;
            RightIndex++;
        }
        else
        {
            var i = 0;
            for (i = RightIndex + 1; i < nRightCharsListLen; i++)
            {
                if (v_LeftCharsList[LeftIndex] == v_RightCharsList[i])
                {
                    RightDiffList[RightDiffList.length] = RightIndex;
                    RightDiffList[RightDiffList.length] = i - 1;

                    LeftIndex++;
                    RightIndex = i + 1;
                    break;
                }
            }

            if (i == nRightCharsListLen)
            {///right is over
                i = 0;
                for (i = LeftIndex + 1; i < nLeftCharsListLen; i++)
                {
                    if (v_RightCharsList[RightIndex] == v_LeftCharsList[i])
                    {
                        LeftDiffList[LeftDiffList.length] = LeftIndex;
                        LeftDiffList[LeftDiffList.length] = i - 1;
                        RightIndex++;
                        LeftIndex = i + 1;
                        break;
                    }
                }
                if (i == nLeftCharsListLen)
                {///left is over, both is diff
                    LeftDiffList[LeftDiffList.length] = LeftIndex;
                    LeftDiffList[LeftDiffList.length] = LeftIndex;
                    RightDiffList[RightDiffList.length] = RightIndex;
                    RightDiffList[RightDiffList.length] = RightIndex;
                    LeftIndex++;
                    RightIndex++;
                }
            }//if (i == nRightCharsListLen)
        }//else
    }//while
    ResultList[0] = LeftDiffList;
    ResultList[1] = RightDiffList;
    return ResultList;
}

function CompareNodes(v_LeftNodesList, v_RightNodesList)
{
    var PreRightIndex =-1;
    var PreLeftIndex =-1;
    var RightIndex =0;
    var LeftIndex =0;
    var nLeftNodesListLen = v_LeftNodesList.length;
    var nRightNodesListLen = v_RightNodesList.length;
    while(LeftIndex <= nLeftNodesListLen || RightIndex <= nRightNodesListLen)
    {
        ///left is end
        if (LeftIndex == nLeftNodesListLen)
        {
            CompareText(GetNodeList(v_LeftNodesList, PreLeftIndex + 1, LeftIndex - PreLeftIndex - 1), GetNodeList(v_RightNodesList, PreRightIndex + 1, RightIndex - PreRightIndex - 1));
            for (var j = RightIndex; j < nRightNodesListLen; j++)
                v_RightNodesList[j] = PaintNode(v_RightNodesList[j], gTEXTBACKCOLOR);
            break;
        }
        ///right is end
        if (RightIndex == nRightNodesListLen)
        {
            CompareText(GetNodeList(v_LeftNodesList, PreLeftIndex + 1, LeftIndex - PreLeftIndex - 1), GetNodeList(v_RightNodesList, PreRightIndex + 1, RightIndex - PreRightIndex - 1));
            for (var j = LeftIndex; j < nLeftNodesListLen; j++)
                v_LeftNodesList[j] = PaintNode(v_LeftNodesList[j], gTEXTBACKCOLOR);
            break;
        }

        if (Equal(v_LeftNodesList[LeftIndex] , v_RightNodesList[RightIndex]))
        {
            if (v_LeftNodesList[LeftIndex].data.length > 1)
            {
                ///same
                CompareText(GetNodeList(v_LeftNodesList, PreLeftIndex + 1, LeftIndex - PreLeftIndex - 1), GetNodeList(v_RightNodesList, PreRightIndex + 1, RightIndex - PreRightIndex - 1));
                PreLeftIndex = LeftIndex;
                PreRightIndex = RightIndex;
            }
            else if (v_LeftNodesList[LeftIndex].data.length == 1 && v_LeftNodesList[LeftIndex].data.charCodeAt(0) > 127)
            {
                PreLeftIndex = LeftIndex;
                PreRightIndex = RightIndex;
            }
            LeftIndex++;
            RightIndex++;
        }
        else
        {
            var i = 0;
            for (i = RightIndex + 1; i < nRightNodesListLen; i++)
            {
                if (Equal(v_LeftNodesList[LeftIndex], v_RightNodesList[i]))
                {
                    if (v_LeftNodesList[LeftIndex].data.length > 1)
                    {
                        CompareText(GetNodeList(v_LeftNodesList, PreLeftIndex + 1, LeftIndex - PreLeftIndex - 1), GetNodeList(v_RightNodesList, PreRightIndex + 1, i - PreRightIndex - 1));

                        PreLeftIndex = LeftIndex;
                        PreRightIndex = i;
                        LeftIndex++;
                        RightIndex = i + 1;
                    }
                    else
                    {
                        if (v_LeftNodesList[LeftIndex].data.length == 1 && v_LeftNodesList[LeftIndex].data.charCodeAt(0) > 127)
                        {
                            PreLeftIndex = LeftIndex;
                            PreRightIndex = RightIndex;
                        }
                        RightIndex++;
                        LeftIndex++;
                    }
                    break;
                }
            }

            if (i == nRightNodesListLen)
            {///right is over
                i = 0;
                for (i = LeftIndex + 1; i < nLeftNodesListLen; i++)
                {
                    if (Equal(v_RightNodesList[RightIndex] , v_LeftNodesList[i]))
                    {
                        if (v_LeftNodesList[i].data.length > 1)
                        {
                            CompareText(GetNodeList(v_LeftNodesList, PreLeftIndex + 1, i - PreLeftIndex - 1), GetNodeList(v_RightNodesList, PreRightIndex + 1, RightIndex - PreRightIndex - 1));
                            PreLeftIndex = i;
                            PreRightIndex = RightIndex;
                            RightIndex++;
                            LeftIndex = i + 1;
                        }
                        else
                        {
                            if (v_LeftNodesList[LeftIndex].data.length == 1 && v_LeftNodesList[LeftIndex].data.charCodeAt(0) > 127)
                            {
                                PreLeftIndex = LeftIndex;
                                PreRightIndex = RightIndex;
                            }
                            RightIndex++;
                            LeftIndex++;
                        }
                        break;
                    }
                }
                if (i == nLeftNodesListLen)
                {///left is over, both is diff
                    LeftIndex++;
                    RightIndex++;
                }
            }//if (i == nRightNodesListLen)
        }//else
    }//while
}

function GetNodeList(v_nodesList, v_begin, v_len)
{
    var List = new Array;
    for (var j = 0; j < v_len; j++)
    {
        List[j] = v_nodesList[v_begin + j];
    }
    return List;
}

function PaintNode(v_node, v_color)
{
    var new_Node = document.createElement('SPAN');
    var colorname = v_color;
    new_Node.style.background = v_color;

    var childNodeCopy = v_node.cloneNode(true);
    new_Node.appendChild(childNodeCopy);

    var fatherNode = v_node.parentNode;
    fatherNode.replaceChild(new_Node, v_node);

    v_node = childNodeCopy;
    return v_node;
}
function LTrim(s)
{
    return s.replace( /^\s*/, "");
}
function RTrim(s)
{
    return s.replace( /\s*$/, "");
}
function Trim(s)
{
    return RTrim(LTrim(s));
}
function GetAllTextNodes(v_fatherNode)
{
    var nodesList = new Array;
    var layer = v_fatherNode.childNodes;
    var childNum = layer.length;

    for (var i = 0; i < childNum; i++)
    {
        var childNode = layer[i];
        var noteType = childNode.nodeType;
        if (3 == noteType && 0 != Trim(childNode.data).length) /* Text node */
        {
            nodesList[nodesList.length] = childNode;
        }
        if (1 == noteType) /* Element node */
        {
            nodesList = nodesList.concat(GetAllTextNodes(childNode));
        }
    }
    return nodesList;
}